﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ReversiBackend;

namespace ReversiFrontend
{

    public delegate void CellClickedHandler(Cell cell);
    
    
    public partial class BoardControl : UserControl
    {

        public event CellClickedHandler CellClicked;

        private Board board;
        public Board Board
        {
            get
            { return board; }
            set
            {
                board = value;
                if (value != null)
                {
                    board.BoardChanged += new ReversiBackend.Board.BoardChangedHandler(board_BoardChanged);

                    board_BoardChanged(null, false);
                }
            }
        }

        private bool showValidFields;
        public bool ShowValidFields
        {
            get
            { return showValidFields; }
            set
            {
                showValidFields = value;
                ShowHints();
            }
        }

        void board_BoardChanged(Cell? c, bool playerMove)
        {
            // update cell value(s) from board
            if (c != null)
            {
                cells[c.Value.X, c.Value.Y].Value = board[c.Value];
                if (playerMove)
                {
                    cells[c.Value.X, c.Value.Y].IsLastPlayerMove = true;
                }
                
            }
            else
            {
                for (int x = 0; x < 8; x++)
                {
                    for (int y = 0; y < 8; y++)
                    {
                        cells[x,y].Value = board[new Cell(x,y)];
                    }
                }
            }
        }

        private CellControl[,] cells = new CellControl[8,8];
        
        public BoardControl()
        {
            InitializeComponent();
            DoubleBuffered = true;
            CellControl c;
            this.BaseColor = Color.Brown;
            for(int x=0; x<8;x++){
                for(int y=0; y<8;y++){
                    c = new CellControl(new Cell(x, y));
                    c.Value = 0;// (x + y) % 3 - 1;
                    cells[x, y] = c;
                    c.Click += new EventHandler(Cell_Clicked);
                    this.Controls.Add(c);
                }
            }
            InvalidFieldEvent += new InvalidFieldEventHandler(BoardControl_InvalidFieldEvent);
            LayoutCells();

            ResizeRedraw = true;
        }


        void Cell_Clicked(object sender, EventArgs e)
        {
            if (CellClicked != null)
            {
                CellClicked((sender as CellControl).Cell);
            }
        }

        public delegate void InvalidFieldEventHandler(Cell c);
        public static event InvalidFieldEventHandler InvalidFieldEvent;
        public static void MarkAsInvalidField(Cell c)
        {
            if (InvalidFieldEvent != null)
            {
                InvalidFieldEvent(c);
            }
        }
        void BoardControl_InvalidFieldEvent(Cell c)
        {
            this.cells[c.X, c.Y].IsClickedInvalidField = true;
        }



        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            LayoutCells();
            Invalidate(true);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            LayoutCells();
            Invalidate(true);
        }

        private static Color baseColor = Color.FromArgb(0, 192, 0);
        public Color BaseColor
        {
            get
            {
                return baseColor;
            }
            set
            {
                if (value != baseColor)
                {
                    baseColor = value;
                    if (baseColor == Color.Brown)
                    {
                        this.BackColor = Color.Transparent;
                        this.BackgroundImage = Properties.Resources.wood;
                        BackgroundImageLayout = ImageLayout.Tile;
                    }
                    else if (baseColor == Color.DarkSlateGray)
                    {
                        this.BackColor = Color.Transparent;
                        this.BackgroundImage = Properties.Resources.slime;
                        BackgroundImageLayout = ImageLayout.Tile;
                    }
                    else
                    {
                        this.BackgroundImage = null;
                        this.BackColor = value;
                    }
                    Refresh();
                }
            }
        }
        public static Color BaseColorGetter
        {
            get
            {
                return baseColor;
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            
            // cell width / height
            double cw = (Width-2) / 8.0, ch = (Height-2) / 8.0;
            // draw lines with two pens (=colors) to get a little (3d-like) sunken effect
            Pen p = new Pen(new SolidBrush(ControlPaint.Dark(baseColor, 0.2f))/*Brushes.DarkGreen*/, 1);
            Pen p2= new Pen(Brushes.Black, 1);
            //Pen p = new Pen(Brushes.Gray, 1);
            //Pen p2 = new Pen(Brushes.DarkGray, 1);
            for (int i = 0; i < 9; i++)
            {
                // lower horizontal
                e.Graphics.DrawLine(p2, new Point(0, (int)(i * ch) + 1), new Point(Width, (int)(i * ch) + 1));
                // left vertical
                e.Graphics.DrawLine(p, new Point((int)(i * cw), 0), new Point((int)(i * cw), Height));
                
                // upper horizontal
                e.Graphics.DrawLine(p, new Point(0, (int)(i * ch)), new Point(Width, (int) (i * ch)));
                // right vertical
                e.Graphics.DrawLine(p2, new Point((int)(i * cw) + 1, 0), new Point((int)(i * cw) + 1, Height));
                
                
                
            }
        }

        /// <summary>
        /// Positioniert alle Zellen und passt ihre Größe an, sodass
        /// sie das Control vollständig ausfüllen.
        /// </summary>
        private void LayoutCells()
        {
            // cell width / height
            double cw = (Width - 2) / 8.0, ch = (Height - 2) / 8.0;
            Size cellSize = new Size((int)cw - 3, (int)ch -3);
            foreach (CellControl c in cells)
            {
                c.Size = cellSize;

                c.Top = (int) (c.Cell.Y * ch) + 3;
                c.Left = (int)(c.Cell.X * cw) + 3;
            }

            Invalidate(true);
        }

        // init mit unerlaubtem wert
        private int currentPlayer = 0;
        // wird in GUI an Game.CurrentPlayerChanged event gebunden
        public void SetCurrentPlayer(int CurrentPlayer)
        {
            currentPlayer = CurrentPlayer;
            ShowHints();
        }

        private void ShowHints()
        {
            if (currentPlayer != 0)
            {
                var validMoves = board.GetValidMoves(currentPlayer);
                foreach (CellControl c in cells)
                {
                    if (ShowValidFields)
                    {
                        c.IsValidField = validMoves.Contains(c.Cell);
                    }
                    else
                    {
                        c.IsValidField = null;
                    }
                }
            }
        }
    }
}
